<?php
/**
 * ShopEx licence
 *
 * @copyright  Copyright (c) 2005-2010 ShopEx Technologies Inc. (http://www.shopex.cn)
 * @license  http://ecos.shopex.cn/ ShopEx License
 */

/**
 * 订单促销过滤
 * $ 2010-05-04 17:30 $
 */
class b2c_cart_postfilter_promotion implements b2c_interface_cart_postfilter {
    private $app;
    private $_rules = null;
    private $FREE_SHIPPING_ITEM = 1;
    private $FREE_SHIPPING_ORDER = 2;

    // @mo 添加另外一个临时rules，防止数据交错导致某些条件被覆盖
    private $temp_rules = null;
    private $temp_use_rules = null;
    public function __construct(&$app){
        $this->app = $app;//b2c
        $this->o_cond = kernel::single('b2c_sales_order_aggregator_combine');
        $this->o_sales_order = $this->app->model('sales_rule_order');

    }

    public function filter(&$aData,&$aResult,$aConfig = array()) {


         
        $this->use_rules = $this->pass_rules = $this->all_rules = $this->_rules = null;

    
        // 取出符合当前购物车条件的规则(已经使用了conditions过滤)@mopoint
        $this->_filter_rules($aData,$aResult,$aConfig);
        //$this->_rules 获取数据库中的规则,并且部分数据反序列化为数组


 
         
        // 只是对goods进行处理待解决 其它类型购物车项待扩展
     if(!isset($aResult['object']['goods']) || !is_array($aResult['object']['goods'])) return false;

        if( $aResult['object']['goods'] ) {
            //$a = 0;
            foreach($aResult['object']['goods'] as &$object) {
                //判断预售
                if($object['prepare_type']!='prepare')
                $this->_apply_to_item($object,$aResult);
                //$a++;
          
            }

        } else {
            //原促销只针对于商品。但订单中包含礼包等信息时。应用于整个购物的促销无法应用。 故追加如下 2011-2-28 16:08
            $num = 0;
            foreach( kernel::servicelist('b2c_cart_object_apps') as $o ) {
                if( $o->intopromotion ) { //标识该类型“商品” 是否计入订单促销范围
                    if( method_exists($o,'get_type') )
                    $tmp[] = $o->get_type();
                }
            }

            if( $tmp ) {
                foreach($aResult['object'] as $_key => &$row) {
                    if( in_array($_key,$tmp) && $row ){
                        foreach($row as &$object) {
                            $this->_apply_to_item($object,$aResult);
                        }
                    }
                }

            }
            //End
        }
        #print_r($aResult);exit;


        if(isset($aResult['object']['coupon']) && !empty($aResult['object']['coupon'])) {
            foreach ($aResult['object']['coupon'] as &$val) {
                if(isset($this->all_rules[$val['rule_id']])) {
                    $val['name'] = $this->all_rules[$val['rule_id']]['cpns_name'];
                    $val["description"] = $aResult['promotion']['coupon'][$val['rule_id']]['desc'];//$this->all_rules[$val['rule_id']]['description'];
                    if(!$this->use_rules || !is_array($this->use_rules)) continue ;
                    if(isset($this->use_rules[$val['rule_id']])) {
                        if(!$this->use_rules[$val['rule_id']]['show'])  $val['used'] = true;
                        $this->use_rules[$val['rule_id']]['show'] = true;
                    }
                } else {
                    $val['name'] = $val['coupon'];
                    $val["description"] = '<font color="red">'.app::get('b2c')->_('该优惠券可能已过期或未启用！').'~</font>';
                }


            }
        }

        $this->dehistory();


    }



    // 初始化订单促销规则(根据当前时间,登录用户等级 从数据库中取出订单促销规则)
    private function _init_rules($aData){
        if (!$this->_rules){
            $mSRO = $this->o_sales_order;
            $arrMemberInfo = kernel::single("b2c_cart_objects")->get_current_member();
 

            $aFilter = array(
                'member_lv' => ($arrMemberInfo['member_lv'] ? $arrMemberInfo['member_lv'] : -1), // todo 这里要改成登录用户的会员等级
                'current_time' => time(),
                'platform' => ($aData['apply_platform'] ? $aData['apply_platform'] : '-1'), //这里要改成所属平台
                // 'office_id'=> ($arrMemberInfo['office_id'] ? $arrMemberInfo['office_id'] : '-1'), //@mo 改是否存在的办事处
                );

            $sSql = "SELECT sdb_b2c_sales_rule_order.rule_id,sdb_b2c_sales_rule_order.name,cpns_name, description, conditions, action_conditions, action_solution, free_shipping, stop_rules_processing, rule_type,office_ids FROM `sdb_b2c_sales_rule_order` LEFT JOIN `sdb_b2c_coupons` ON `sdb_b2c_sales_rule_order`.rule_id = `sdb_b2c_coupons`.rule_id
                         WHERE ". $this->_filter_sql($aFilter) ."
                         ORDER BY  sort_order ASC,  sdb_b2c_sales_rule_order.rule_id DESC";

            $this->_rules = $mSRO->db->select($sSql);
        
            is_array($this->_rules) or $this->_rules=array();

            foreach($this->_rules as $_k => &$rule) {
                foreach($rule as $_k1 => &$value) {
                    if(in_array($_k1, array('rule_id', 'description', 'cpns_name', 'rule_type', 'free_shipping','name'))) continue;
                    if(in_array(strtolower($value), array('true', 'false'))) {
                        $value = (strtolower($value)=='true') ? true : false;
                        continue;
                    }
                    $value = is_array($value) ? $value : unserialize($value);

                }
            }
        }

        //另外保存临时的rules
        $this->temp_rules = null;
        $this->temp_rules = $this->_rules;

        return true;
    }

    // 开发这个 主要是为了测试用例的
    public function getRule() {
        return $this->_rules;
    }

    private function _init_rules_order($aConfig) {
        // todo 订单修改时初始化 需要处理的规则
    }




    private function _filter_sql($aFilter) {

            
        $aWhere[] = "status = 'true'"; // 开启状态

        if (isset($aFilter['member_lv'])){
            $aWhere[] = sprintf(' (find_in_set(\'%s\', member_lv_ids))', $aFilter['member_lv']);
            unset($aFilter['member_lv']);
        }

        if (isset($aFilter['platform'])){
            $aWhere[] = sprintf(' (find_in_set(\'%s\', apply_platform))', $aFilter['platform']);
            unset($aFilter['platform']);
        }
        if (isset($aFilter['current_time'])){
            $aWhere[] = sprintf(' (%s >= from_time or from_time=0)',
                               $aFilter['current_time']);
            $aWhere[] = sprintf(' (%s <= to_time or to_time=0)', $aFilter['current_time']);
            unset($aFilter['current_time']);
        }

        //@mo 2017年4月13日 13:26:34 添加办事处限制
        //  if (isset($aFilter['office_id'])){
        //     $aWhere[] = sprintf(' (find_in_set(\'%s\', office_ids))', $aFilter['office_id']);
        //     unset($aFilter['office_id']);
        // }

           
        return implode(' AND ',$aWhere);
    }



     /**
      @mo
     * 过滤订单促销规则(cart_objects符合conditions 的促销规则) 获取当前符合的促销规则
     *
     * @param array $cart_objects
     */

    public function get_filter_rules($aData,$cart_objects,$aConfig = array()){

        if(!empty($aConfig)) {
            $this->_init_rules_order($aConfig);
       
        } else {
            if (!$this->temp_rules) $this->_init_rules($aData);//初始获取后台可以使用的优惠规则
        }
        

        $validated = false;
        //由于_filter_rules俩个同时操作了$this->_rules,
        //可能导致首批打折那取消了某些优惠条件，所以要单独保存相关数据
        foreach($this->temp_rules as $_k => $rule){

            $oCond = $this->o_cond;//b2c_sales_order_aggregator_combine

            $this->all_rules[$rule['rule_id']] = $rule;
            $validated = $oCond->validate($cart_objects,$rule['conditions']);//判断当前rule是否能促发
            if(!$validated){
                unset($this->temp_rules[$_k]);//把不符合的规则释放
            }

        }
        return $this->temp_rules;
    }



    /**
     * 过滤订单促销规则(cart_objects符合conditions 的促销规则) 去掉当前购物车内不符合的促销规则
     *
     * @param array $cart_objects
     */
    private function _filter_rules($aData,$cart_objects,$aConfig = array()){
        
        if(!empty($aConfig)) {
            $this->_init_rules_order($aConfig);
       
        } else {
            if (!$this->_rules) $this->_init_rules($aData);//初始获取后台可以使用的优惠规则

          
        }
        
        $validated = false;
        foreach($this->_rules as $_k => $rule){

            $oCond = $this->o_cond;//b2c_sales_order_aggregator_combine

            $this->all_rules[$rule['rule_id']] = $rule;
            // $validated = $oCond->validate($cart_objects,$rule['conditions']);//判断当前rule是否能促发
             $validated = $oCond->validate_me($cart_objects,$rule);//判断当前rule是否能促发
            if(!$validated){
                unset($this->_rules[$_k]);//把不符合的规则释放
            }

        }

    }



    /**
     * 订单页面未执行的促销
     *
     * @param array $cart_objects
     */
    public function get_unuse_rule($cart_objects){
        if(!empty($aConfig)) {
            $this->_init_rules_order($aConfig);
        } else {
            if (!$this->_rules) $this->_init_rules($cart_objects);
        }

// var_dump($this->_rules);
        $validated = false;
        foreach($this->_rules as $_k => $rule){
            $oCond = $this->o_cond;
            if( strtolower($rule['rule_type'])=='c' ) continue;
            $validated = $oCond->validate($cart_objects,$rule['conditions']);
            if(!$validated){
                $s = $oCond->get_unuse_rule( $cart_objects,$rule );
                //if( !$s ) continue;
                $solution = $rule['action_solution'];
                reset( $solution );
                @kernel::single(key($solution))->setString(current($solution));
                if(method_exists(@kernel::single(key($solution)),'get_desc_tag'))
                    $desc_tag = @kernel::single(key($solution))->get_desc_tag(); //优惠标签
                //$return[$_k]['desc'] = $s;
                $return[$_k]['name'] = $rule['name'];
                $return[$_k]['solution'] = @kernel::single(key($solution))->getString();
                $return[$_k]['desc_tag'] = $desc_tag['name'] ;
                unset($this->_rules[$_k]);
            }
        }
        // var_dump($return);
        return $return;
    }

    private function _apply_action(&$object, &$cart_object, &$rule) {

        //优惠方案不存在直接返回
        if(!$rule['action_solution']) return false;
        foreach ($rule['action_solution'] as $key => &$val) {
            if($val['used']) continue;

            if(!is_string($key))continue;

            $o = kernel::single($key);
            if(method_exists($o, 'get_status')) {
                if(!$o->get_status()) return false;
            }


            $o->rule_id = $rule['rule_id'];
            $o->type = (strtolower($rule['rule_type'])=='c') ? 'coupon' : $val['type'];
            //针对于符合条件的商品
            if($val['type']=='goods') {
                //商品促销中。同种方案在同一商品上 适用 排他原则 addtime 2011-2-23 16:03
                //我最想要的效果是：最后应用的规则是最终生效的规则
                $pid = $object['obj_items']['products'][0]['product_id'];
                if( $this->__stop_rules_processing_goods[$key][$pid] ) {
                    $this->__stop_rules_processing_goods[$key][$pid];
                    kernel::single($key)->setString($val);
                    continue;
                }
                if( $o->stop_rule_with_same_solution ) {
                    $this->__stop_rules_processing_goods[$key][$pid] = $val;
                }
        // $data['val'] =  $val;
        // $data['rule'] =  $rule;
        // file_put_contents("0000000000_apply_data.txt", var_export($data, 1).PHP_EOL, FILE_APPEND);
        // ###################################
                // $o->apply($object, $val, $cart_object);
                ////@mo 应用模板中方法
                 $o->apply($object, $val,$rule, $cart_object);
                //////////
            } else {
        // $data2['val'] =  $val;
        // $data2['rule'] =  $rule;
        // file_put_contents("0000000000_apply_order_data.txt", var_export($data2, 1).PHP_EOL, FILE_APPEND);
        // ###################################
                //订单
                $flag = $o->apply_order($object, $val, $cart_object);
                
                // @mo 应用模板中方法
                // $flag = $o->apply_order($object, $val,$rule, $cart_object);
                ///////
                if($flag === false){
                    return false;
                }
                $val['used'] = true;
            }

        }
        return $key;
    }

    private function _apply_to_item(&$object, &$cart_object){

        $oCond = $this->o_cond;
//                                 echo '<pre>';
//        print_r($this->_rules);
//        echo '<br>======<br>';
//        exit;

        $arr_use_rule = array();
        foreach($this->_rules as &$rule) {
                //$rule['rule_type'] = n//类型
                if( $this->stop_rules_processing[$rule['rule_type']] && $this->stop_rules_processing[$rule['rule_type']]!==$rule['rule_id'] ) continue;
                // 如果action_conditions['conditions']不为空 验证要否对此商品进行优惠  为空 表示对全部购物车商品
                if(isset($rule['action_conditions']['conditions']) && !empty($rule['action_conditions']['conditions'])) {
                    // 不符合则跳过
                    if (!$oCond->validate($object, $rule['action_conditions'])) 
                        continue;
                    }

                    // 是否免运费
                    switch($rule['free_shipping']){
                        case $this->FREE_SHIPPING_ITEM:
                            $object['is_free_shipping'] = true;
                            break;
                        case $this->FREE_SHIPPING_ORDER:
                            $cart_object['is_free_shipping'] = true;
                            break;
                    }

                    $this->all_rules[$rule['rule_id']] = $rule;


                    //用户适用的订单规则
                    $arr_use_rule[$rule['rule_type']][] = &$rule;
                    if( $rule['stop_rules_processing'] ) {
                        $this->stop_rules_processing[$rule['rule_type']] = $rule['rule_id'];
                    }
        }


          
        if( isset($arr_use_rule) && is_array($arr_use_rule) ) {
            
 
            foreach( $arr_use_rule as $arr ) {
                if( is_array($arr) ) {
                    foreach( $arr as $tmp_use_rule ) {
//                                    echo '<pre>';
//        print_r($tmp_use_rule);
//        echo '<br>======<br>';
//        exit;
                        if( $this->use_rules[$tmp_use_rule['rule_id']]['rule_used']==true ) continue;
            if( !$this->use_rules[$tmp_use_rule['rule_id']] )
                $this->use_rules[$tmp_use_rule['rule_id']] = $tmp_use_rule;

            //临时记录优惠价格 to：记录每个规则针对于商品的优惠 商超
            $tmp_promotion_amount = $object['discount_amount_order'];


            // 执行优惠处理
                        if( !is_array($tmp_use_rule['action_solution']) ) continue;
            reset( $tmp_use_rule['action_solution'] );

            //优惠方案的具体lib文件名
            $temp_solution_name = key($tmp_use_rule['action_solution']);
            if( empty($object) ) {
                if( !kernel::single($temp_solution_name)->actiontoall ) {
                    unset( $this->use_rules[$tmp_use_rule['rule_id']] );
                                continue;
                }
            }

            //应用场景：1.促销应用于整个订单 2.订单中没有商品（如只添加了礼包进入购物车）
            //此时传入object为空！  默认不允许应用“符合条件的商品”类促销
            if( 'goods'==$tmp_use_rule['action_solution'][$temp_solution_name]['type'] ) {
                            if( !$object ) continue;
            } 
            
            $flag = $this->_apply_action($object, $cart_object, $tmp_use_rule); 
 
            if($flag === false){
                continue;
            }

            //优惠执行成功时返回解决方案适用的lib
            if($temp_solution_name) {

                //规则针对商品时处理购物车内所有符合条件的商品
                $solu_u_type = $tmp_use_rule['action_solution'][$temp_solution_name]['type'];
                if($solu_u_type=='goods') {
                   $this->pass_rules[$tmp_use_rule['rule_id']] = true;
                } else {
                    $this->use_rules[$tmp_use_rule['rule_id']]['rule_used'] = true;
                }

                //购物车：应用的优惠方案显示

                $oDefault = kernel::single($temp_solution_name);
                $obj_math = kernel::single("ectools_math");
                $tmp_promotion_name = 'order';
                if(method_exists($oDefault, 'get_desc_tag'))$desc_tag = $oDefault->get_desc_tag(); //优惠标签

                if( strtolower($tmp_use_rule['rule_type'])=='c' ) $tmp_promotion_name = 'coupon';

                if(isset($cart_object['promotion'][$tmp_promotion_name][$tmp_use_rule['rule_id']])) {
                    if($oDefault->score_add) continue;
                    $cart_object['promotion'][$tmp_promotion_name][$tmp_use_rule['rule_id']]['discount_amount'] = $obj_math->number_plus(array($cart_object['promotion'][$tmp_promotion_name][$tmp_use_rule['rule_id']]['discount_amount'],$obj_math->number_minus(array($object['discount_amount_order'],$tmp_promotion_amount))));
                    if( $solu_u_type=='goods' && empty($rule['description']) )
                        $cart_object['promotion'][$tmp_promotion_name][$tmp_use_rule['rule_id']]['desc'] = $object['obj_items']['products'][0]['new_name'] .'、'. $cart_object['promotion'][$tmp_promotion_name][$tmp_use_rule['rule_id']]['desc'];
                } else {
                    $cart_object['promotion'][$tmp_promotion_name][$tmp_use_rule['rule_id']] = array(
                        'name' => $tmp_use_rule['name'],
                        'rule_id'   =>  $tmp_use_rule['rule_id'],
                        'discount_amount' =>  0,
                        'desc'  => ( empty($rule['description']) ? ( ( $solu_u_type=='goods' ? $object['obj_items']['products'][0]['new_name'] : '' ) . $oDefault->getString() ) : $tmp_use_rule['description'] ),
                        'solution' => $oDefault->getString(),
                        'desc_tag' => $desc_tag['name'],
                    );
                                if($oDefault->score_add) continue;
                    $cart_object['promotion'][$tmp_promotion_name][$tmp_use_rule['rule_id']]['discount_amount'] = $obj_math->number_minus(array($object['discount_amount_order'],$tmp_promotion_amount));
                }
                

                //记录商品享受的促销 商超
                $obj_key = $object['obj_items']['products'][0]['product_id'];
                $cart_object['promotion_solution'][$obj_key]['goods_id'] = $object['obj_items']['products'][0]['goods_id'];
                $cart_object['promotion_solution'][$obj_key]['order'][] = array(
                                                                'rule_id' => $tmp_use_rule['rule_id'],
                                                                'amount'  => ($object['discount_amount_order']-$tmp_promotion_amount),
                                                                'type' => $tmp_use_rule['action_solution'][$temp_solution_name]['type'],
                                                            );


            }
            
             if($tmp_use_rule['conditions']['conditions'][0]['type2']=='FirstDiscount'){
                    $pre_rule = app::get('b2c')->model('sales_rule_order');
                    $filter_c = array('rule_id'=>$tmp_use_rule['rule_id']);//bug 缺少时间判断  @mo 获取当前时间在促销规则之内的促销规则
                    $time = $pre_rule->getList('to_time,from_time', $filter_c, 0, -1, 'rule_id ASC');
//                   //add by hzk 06-08
                   $data['conditions']['conditions'][0]['conditions'][0]['value'] = $tmp_use_rule['conditions']['conditions'][0]['conditions'][0]['value'];
                   $data['from_time']= $time[0]['from_time'];
                   $data['to_time']= $time[0]['to_time'];
                   $data['type2']= $tmp_use_rule['conditions']['conditions'][0]['type2'];
                  $num_in_order= kernel::single('b2c_checkproduct_check')->get_number_from_rule_in_order($data);
                  
                $num_in_order =($num_in_order<$tmp_use_rule['conditions']['conditions'][0]['firstvalue'])?$num_in_order : $tmp_use_rule['conditions']['conditions'][0]['firstvalue'];
                $cart_object['promotion'][$tmp_promotion_name][$tmp_use_rule['rule_id']]['num_in_order_warming'] = ($num_in_order<$tmp_use_rule['conditions']['conditions'][0]['firstvalue'])?'已享优惠数量： '.$num_in_order.' 个':'已达到优惠数量封顶： '.$num_in_order.' 个';//
            }//add end
            
        }
    }
            }
        }
//                             echo '<pre>';
//                print_r($cart_object['promotion']['order']);
//        echo '<br>======<br>';
//        exit;
    }




    private function dehistory() {
        $this->use_rules = $this->pass_rules = $this->all_rules = $this->_rules = $this->stop_rules_processing = $this->__stop_rules_processing_goods = null;
    }
    
//     public function get_number_from_rule_in_order($rule_protion)
//    {
////echo '<pre>';
////                print_r($rule_protion);
//           $member_id = kernel::single('b2c_user_object')->get_member_id();
//            
//            $db_order = app::get('b2c')->model('orders');
//
//             $fromtime = $rule_protion['from_time'];
//           $totime=$rule_protion['to_time'];
//             $filter1 = array('member_id'=>$member_id,'createtime|bthan'=>$fromtime,'createtime|sthan'=>$totime,'status|noequal'=>'dead');//modify by hzk 05-26 排除废单 status = dead
//       
//// echo '<br>==111====<br>';
//           //根据当前的促销条件到订单中心去获取当前这个人已经购买的数量
//            $this_member_all_orders = $db_order->getList('order_id,member_id,createtime');
////            $this_member_all_orders = $db_order->getList('order_id,member_id,createtime', $filter, 0, -1, 'order_id ASC');
////echo '<pre>'; 
////                print_r($filter1);
//// echo '<br>==222====<br>';
////                print_r($this_member_all_orders);
//// echo '<br>======<br>';
//  
//            $db_order_goods = app::get('b2c')->model('order_items');
//            $gift_type = app::get('b2c')->_('product');
//            //促发条件的 个数 $rule_protion['conditions']['conditions'][0]['value']
//            
//            $order_goods_nums = 0;//当前用户之前购买的数量
//            foreach ($this_member_all_orders as $one_order) {
//                $temp_filter = array('order_id'=>$one_order,'item_type|nequal'=>$gift_type,'goods_id'=>$rule_protion['conditions']['conditions'][0]['conditions'][0]['value']);
//                $temp_goods = $db_order_goods->getList('goods_id,name,nums,order_id', $temp_filter, 0, -1, 'order_id ASC');
//
//                    $order_goods_nums += (int)$temp_goods[0]['nums'];//总计订单中该商品的个数
////            echo '<pre>';
////                print_r($rule_protion);
////                print_r($temp_filter);
////        echo '<br>======<br>';
//            }
//            return  $order_goods_nums;
//    }
    

}

